/**
 * The contents of this file are subject to the license and copyright detailed in the LICENSE and NOTICE files at the root of the source tree and available online at
 * http://www.askosi.org/license.html
 */
package be.destin.skos.core;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

public class ConceptUse {

	/** log4j category */
	private static Logger log = Logger.getLogger(ConceptUse.class);
/*	
	private static final Pattern patSubField = Pattern.compile("\\b"+SkosManager.aboutSubfields+'\\'+SchemeInterface.separator+"([a-zA-Z0-9]+)\\b");
*/
	private static final Pattern nonWordSeparator = Pattern.compile("\\W+");
/*
	private static final Pattern patSplitSubField = Pattern.compile( "\\b\\"+SchemeInterface.separator+"([a-zA-Z0-9]+)\\"+SchemeInterface.separator+"\\b");
*/	
	MetadataProperty field;
	LinkedList<String> prefix = new LinkedList<String>();
	Concept concept = null;
	LinkedList<String> suffix = new LinkedList<String>();
	String additionalInfo = "";
/*
	HashMap<String,ConceptUse> subfields = new HashMap<String,ConceptUse>();
*/
	public ConceptUse(SkosManager skosManager, String value) {
		if (value != null && !value.isEmpty() && !parse(skosManager, null, value))
			log.debug(value+" unrecognized.");
	}

	public ConceptUse(MetadataProperty field) {
		this.field = field;
	}

	public ConceptUse(SkosManager skosManager, MetadataProperty field, String value) {
		this.field = field;
		if (value != null && !value.isEmpty() && !parse(skosManager, field, value))
			log.info("Field "+field.toString()+", value="+value+" unrecognized.");
	}
/*
	private ConceptUse(SkosManager skosManager, MetadataProperty field, String subfield, String value) {
		if (value != null && !parse(skosManager, field, subfield, value))
			log.info("Field "+field.toString()+", subfield "+subfield+", value="+value+" unrecognized.");
	}
*/
	private boolean parse(SkosManager skosManager, MetadataProperty field, /*subfield,*/ String input) {
		this.concept = null;
		this.additionalInfo = "";
		if (input == null) return false;
		input = input.trim();
		if (input.length()==0) return false;
		boolean subst = false;
		boolean closed = false;
/*
		LinkedList<String> subfieldsNames = null;
		HashMap<String,String> parts = null;
 */
		if (field != null){
			closed = this.field.isClosed();
/*			
			if (subfield == null) {
				subfieldsNames = this.field.getSubfield(); 
				if (subfieldsNames.size() > 0) {
					parts = this.subFieldSplit(input);
					input = parts.get(""); // main value
					for (String aField: subfieldsNames) {
						String partValue = parts.get(aField);
						if (partValue != null) {
							String subValue = parts.get(aField);
							if (subValue != null && subValue.length() > 0) {
								String subfieldVal = parts.get(aField);
								if (subfieldVal != null) {
									subfieldVal = subfieldVal.trim();
									if (subfieldVal.length() > 0) {
										subfields.put(aField,new ConceptUse(skosManager,field,aField,subfieldVal));
									}
								}
							}
						}
					}
				}
			} else {
				ConceptScheme subfieldScheme = (ConceptScheme) skosManager.getSubfields();
				if (subfieldScheme != null) {
					field = (MetadataProperty) subfieldScheme.getConcept(subfield);
				}
			}
*/
		}
		int pos = input.indexOf(SchemeInterface.separator);
		while (pos >= 0) {
			int i = pos-1;
			while (i >= 0 && Character.isJavaIdentifierPart(input.charAt(i)))
				i--;
			i++;
			int j = pos+1;
			while (j < input.length() && Character.isJavaIdentifierPart(input.charAt(j)))
				j++;
			String fullHandle = input.substring(i,j);
			Concept aConcept;
			if (field != null)
				aConcept = skosManager.getScheme_Concept(fullHandle,field.getEffectiveDefaultScheme(),field.getEffectiveConceptScheme(), field.getEffectiveNotationScheme());
			else aConcept = skosManager.getScheme_Concept(fullHandle);
			if (aConcept != null) {
				input = (input.substring(0,i)+input.substring(j)).trim();
				if (aConcept.getInScheme().equals(skosManager.getPrefixes()))
					this.prefix.add(aConcept.getAbout());
				else if (aConcept.getInScheme().equals(skosManager.getSuffixes()))
					this.suffix.add(aConcept.getAbout());
				else {
					this.concept = aConcept;
					subst = true;
				}
				pos = input.indexOf(SchemeInterface.separator);
			}
			else pos = input.indexOf(SchemeInterface.separator, j);
		}
		if (subst) {
			additionalInfo = input.trim();
			return true;
		}
		if (input.length()==0) {
			return false;
		}
		if (field == null || field.getDefaultScheme() == null) {
			additionalInfo = input.trim();
			return !closed;
		}
		SchemeInterface aScheme = skosManager.getScheme(field.getDefaultScheme());
		if (aScheme == null) {
			additionalInfo = input.trim();
			return !closed;
		}
		this.concept = aScheme.getConcept(input);
		if (this.concept == null) {
			additionalInfo = input.trim();
			return !closed;
		}
		return true;
	}

	/**
	 * @return the field
	 */
	public MetadataProperty getField() {
		return field;
	}

	/**
	 * @param field the field to set
	 */
	public void setField(MetadataProperty field) {
		this.field = field;
	}

	/**
	 * @return the prefix
	 */
	public LinkedList<String> getPrefix() {
		return prefix;
	}

	public String getPrefixString() {
		if (prefix == null || prefix.size() == 0) return "";
		StringBuffer result = new StringBuffer();
		int max = field.getMaxSuffix();
		for (String aPrefix: prefix) {
			max--;
			if (max < 0) break;
			if (result.length() > 0) result.append(' ');
			result.append(aPrefix.trim());
		}
		return result.toString();
	}
	/**
	 * @param prefix the prefix to set
	 */
	public void setPrefix(LinkedList<String> prefix) {
		this.prefix = prefix;
	}

	/**
	 * @return the concept
	 */
	public Concept getConcept() {
		return concept;
	}

	/**
	 * @param concept the concept to set
	 */
	public void setConcept(Concept concept) {
		this.concept = concept;
	}

	/**
	 * @return the suffix
	 */
	public LinkedList<String> getSuffix() {
		return suffix;
	}

	public String getSuffixString() {
		if (suffix == null || suffix.size() == 0) return "";
		StringBuffer result = new StringBuffer();
		int max = field.getMaxSuffix();
		for (String aSuffix: suffix) {
			max--;
			if (max < 0) break;
			if (result.length() > 0) result.append(' ');
			result.append(aSuffix.trim());
		}
		return result.toString();
	}
	/**
	 * @param suffix the suffix to set
	 */
	public void setSuffix(LinkedList<String> suffix) {
		this.suffix = suffix;
	}
	
	public String toString() {
		String result = "";
		if (this.prefix != null && this.prefix.size() > 0 ) result = result+this.prefix.getFirst()+SchemeInterface.separator+" ";
		if (this.concept != null) result = result+this.concept.getScheme_About()+" ";
		if (this.suffix != null && this.suffix.size() > 0 ) result = result+SchemeInterface.separator+this.suffix.getFirst();
		if (this.additionalInfo != null && this.additionalInfo.length() > 0 ) result = result+" "+additionalInfo;
		return result;
	}

	/**
	 * @return the additionalInfo
	 */
	public String getAdditionalInfo() {
		return additionalInfo;
	}

	/**
	 * @param additionalInfo the additionalInfo to set
	 */
	public void setAdditionalInfo(String additionalInfo) {
		if (additionalInfo == null) this.additionalInfo = null;
		else this.additionalInfo = additionalInfo;
	}

	public static String normPrefix (String stringPrefix) {
		if (stringPrefix == null) return "";
		StringBuffer result = new StringBuffer();

		String[] prefixes = nonWordSeparator.split(stringPrefix);
		if (prefixes != null) {
			for (String aPrefix : prefixes) {
				if (aPrefix.length() > 0) {
					if (aPrefix.startsWith(SkosManager.aboutPrefixes+SchemeInterface.separator)) {
						aPrefix = aPrefix.substring(SkosManager.aboutPrefixes.length()+1)+SchemeInterface.separator;
					}
					if (aPrefix.charAt(aPrefix.length()-1) != SchemeInterface.separator) {
						aPrefix = aPrefix+SchemeInterface.separator;
					}
					if (result.length() > 0) result.append(' ');
					result.append(aPrefix);
				}
			}
		}
		return result.toString();
	}
	
	public static String normSuffix (String stringSuffix) {
		if (stringSuffix == null) return "";
		StringBuffer result = new StringBuffer();

		String[] suffixes = nonWordSeparator.split(stringSuffix);
		if (suffixes != null) {
			for (String aSuffix : suffixes) {
				if (aSuffix.length() > 0) {
					if (aSuffix.startsWith(SkosManager.aboutSuffixes+SchemeInterface.separator)) {
						aSuffix = aSuffix.substring(SkosManager.aboutSuffixes.length());
					}
					else if (aSuffix.charAt(0)!=SchemeInterface.separator) {
						aSuffix = SchemeInterface.separator+aSuffix;
					}
					if (result.length() > 0) result.append(' ');
					result.append(aSuffix);
				}
			}
		}
		return result.toString();
	}
/*
	private static String normSubField (String stringSubfield) {
		if (stringSubfield == null) return "";
		return patSubField.matcher(stringSubfield).replaceAll(SchemeInterface.separator+"$1"+SchemeInterface.separator);
	}

	private static HashMap<String,String> subFieldSplit(String stringComplete) {
		String normedString = normSubField(stringComplete);
		Matcher regexMatcher = patSplitSubField.matcher(normedString);
		HashMap<String,String> parts = new HashMap<String,String>();
		String partID = "";
		int base = 0;
		while (regexMatcher.find()) {
			parts.put(partID, normedString.substring(base,regexMatcher.start(0)));
			partID = regexMatcher.group(1);
			base = regexMatcher.end(0);
		}
		return parts;
	}
	
	public HashMap<String,ConceptUse> getSubfields() {
		return subfields;
	}
*/
}
